package com.spring.proxy;

import com.spring.annotation.Transactional;

import com.spring.factory.DefaultBeanFactory;
import com.spring.util.Manager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyStrategy implements ProxyStrategy {
    @Override
    public <T> T doProxy(T object) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object returnValue = null;
                boolean doTransaction = false;
                Class<?> clazzRollback = null;

                if(o.getClass().isAnnotationPresent(Transactional.class) ){
                    clazzRollback = o.getClass().getAnnotation(Transactional.class).rollbackFor();
                    doTransaction = true;
                } else if(method.isAnnotationPresent(Transactional.class)){
                    clazzRollback = method.getAnnotation(Transactional.class).rollbackFor();
                    doTransaction = true;
                }

                Manager transactionManager = null;
                try{

                    if(doTransaction){
                        transactionManager =  DefaultBeanFactory.getInstance().getBean("transactionManager");
                        transactionManager.beginTransaction();
                    }

                    returnValue = methodProxy.invokeSuper(o, objects);

                    if(doTransaction){
                        transactionManager.commit();
                    }
                } catch (Exception e){
                    transactionManager.rollback();
                    throw e;
                }

                return returnValue;
            }
        });

        return (T)enhancer.create();
    }
}